package model

import (
	"errors"
	jsoniter "github.com/json-iterator/go"
	"honeyweb/log"
)

//code
const (
	E_PARSE       = -32700
	E_INVALID_REQ = -32600
	E_NO_METHOD   = -32601
	E_BAD_PARAMS  = -32602
	E_INTERNAL    = -32603
	E_SERVER      = -32000
)

var (
	ErrEncode = errors.New("Json Marshal error")
)

//信息的额外信息
type Meta map[string]string

type Error struct {
	// A Number that indicates the error type that occurred.
	Code int `json:"code"` /* required */

	// A String providing a short description of the error.
	// The message SHOULD be limited to a concise single sentence.
	Message string `json:"message"` /* required */

	// A Primitive or Structured value that contains additional information about the error.
	Data interface{} `json:"data"` /* optional */
}

func (e *Error) Error() string {
	return e.Message
}

//请求或通知
type JsonReq struct {
	// JSON-RPC protocol.
	Version string `json:"jsonrpc"`

	// 路由方法  一般形式: 服务名.方法名
	Method string `json:"method"`

	// 这个方法的参数. json编码过的字符串
	Params string `json:"params"`

	// 已建立客户端的唯一标识id，服务端必须回答相同的值如果包含在响应对象。
	// 这个成员用来两个对象之间的关联上下文,如果不包含该成员则被认定为是一个通知
	Id int64 `json:"id"`

	//除参数之外的其他信息
	Meta Meta `json: "meta"`
}

//
type JsonResp struct {
	Version string      `json:"jsonrpc"`
	Method  string      `json:"method"`
	Result  string      `json:"result"`
	Error   interface{} `json:"error"`
	Id      int64       `json:"id"`
}

func NewJsonReq(id int64, method string, args interface{}, meta Meta) (*JsonReq, error) {
	params := ""
	if args != nil {
		params = Encode2String(args)
	}
	r := &JsonReq{
		Version: "2.0",
		Method:  method,
		Params:  params,
		Id:      id,
		Meta:    meta,
	}
	return r, nil
}

func NewJsonReqByByte(data []byte) (*JsonReq, error) {
	var r JsonReq
	if err := jsoniter.Unmarshal(data, &r); err != nil {
		return nil, err
	}
	return &r, nil
}

func (req *JsonReq)AddMeta(k, v string) {
	if req.Meta == nil {
		req.Meta = make(Meta)
	}
	req.Meta[k] = v
}

func NewJsonRespByByte(data []byte)(*JsonResp, error) {
	var r JsonResp
	if err := jsoniter.Unmarshal(data,&r); err != nil {
		return nil, err
	}
	return &r, nil
}

func NewErrJsonResp(id int64, method string, code int, msg string) *JsonResp {
	err := &Error{
		Code:    code,
		Message: msg,
	}
	resp := &JsonResp{
		Version: "2.0",
		Method:  method,
		Error:   err,
		Id:      id,
	}
	return resp
}

func NewResultResp(id int64, method, result string) *JsonResp {
	return &JsonResp{
		Version: "2.0",
		Method:  method,
		Result: result,
		Id:      id,
	}
}

func Encode(v interface{}) ([]byte, error) {
	return jsoniter.Marshal(v)
}

func Encode2String(v interface{}) string {
	str, err := jsoniter.MarshalToString(v)
	if err != nil {
		log.S().Error("json marshal error:", err)
		return ""
	}
	return str
}

func DecodeFromString(str string, v interface{}) error {
	return jsoniter.UnmarshalFromString(str, v)
}
